package com.dk.util.http;

import com.dk.enumerate.HttpEnum;
import com.dk.util.config.ReadConfig;
import com.dk.util.http.interceptor.CustomLogInterceptor;
import com.dk.util.http.interceptor.HeaderInterceptor;
import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.HttpUrl;
import okhttp3.OkHttpClient;

import javax.net.ssl.*;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * OKHTTP客户端构建类
 */
public class OkHttpBuild {
    //OkHttp客户端对象
    public static OkHttpClient okHttpClient;

    //初始化Okhttp客户端对象
    static{
        //构建ssl工厂类
        TrustManager[] trustAllCerts = buildTrustManagers();
        final SSLContext sslContext;
        SSLSocketFactory sslSocketFactory = null;
        try {
            sslContext = SSLContext.getInstance(HttpEnum.SSL.getValue());
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
            sslSocketFactory = sslContext.getSocketFactory();
        } catch (NoSuchAlgorithmException | KeyManagementException e) {
            e.printStackTrace();
        }
        okHttpClient = new OkHttpClient.Builder()
                .connectTimeout(Integer.parseInt(ReadConfig.CONNECTTIMEOUT), TimeUnit.SECONDS)//连接超时时间
                .writeTimeout(Integer.parseInt(ReadConfig.WRITETIMEOUT),TimeUnit.SECONDS)//写入超时时间
                .readTimeout(Integer.parseInt(ReadConfig.READTIMEOUT),TimeUnit.SECONDS)//读取超时时间
                .followRedirects(false)//禁止重定向
                .followSslRedirects(false)//禁止https->http或者http->https的重定向
                //.sslSocketFactory(sslSocketFactory)//注册ssl连接工厂,这一行JDK9以上适用，JDK8把第二个参数去掉,第二个参数:(X509TrustManager) trustAllCerts[0]
                .hostnameVerifier(new HostnameVerifier() {
                    @Override
                    public boolean verify(String hostname, SSLSession session) {
                        return true;
                    }
                })//所有主机信任访问
                .retryOnConnectionFailure(false)//连接失败禁止重试
                .addInterceptor(new HeaderInterceptor())//注册添加公共头部拦截器
                .addInterceptor(new CustomLogInterceptor())//注册日志打印拦截器
                .cookieJar(new CookieJar() {//添加cookie管理器
                    //cookie管理集合
                    private final HashMap<HttpUrl, List<Cookie>> cookieStore = new HashMap<HttpUrl,List<Cookie>>();

                    /**
                     * 从响应保存Cookie
                     * @param httpUrl 地址对象
                     * @param list cookie集合
                     */
                    @Override
                    public void saveFromResponse(HttpUrl httpUrl, List<Cookie> list) {
                        //将地址对象和cookie集合存入管理集合
                        cookieStore.put(httpUrl,list);
                    }

                    /**
                     * 请求加载cookie
                     * @param httpUrl 地址对象
                     * @return cookie集合
                     */
                    @Override
                    public List<Cookie> loadForRequest(HttpUrl httpUrl) {
                        //通过地址对象获取cookie集合对象
                        List<Cookie> cookies = cookieStore.get(httpUrl);
                        //当获取的cookie集合不为空时,返回获取的cookie集合,反之,则新建一个空cookie集合返回
                        return cookies!=null ? cookies : new ArrayList<Cookie>();
                    }
                })
                .build();
    }

    /**
     *构建信任控制器
     * @return
     */
    private static TrustManager[] buildTrustManagers() {
        return new TrustManager[]{
                new X509TrustManager() {
                    @Override
                    public void checkClientTrusted(java.security.cert.X509Certificate[] chain, String authType) {
                    }

                    @Override
                    public void checkServerTrusted(java.security.cert.X509Certificate[] chain, String authType) {
                    }

                    @Override
                    public java.security.cert.X509Certificate[] getAcceptedIssuers() {
                        return new java.security.cert.X509Certificate[]{};
                    }
                }
        };
    }
}
